package com.uff.hmstpa.model.persistence.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;

import com.uff.hmstpa.model.domain.Appointment;
import com.uff.hmstpa.model.persistence.AbstractModelDAO;
import com.uff.hmstpa.model.persistence.AppointmentDAO;

public class AppointmentDAOImpl extends AbstractModelDAO implements AppointmentDAO {

	private static AppointmentDAOImpl SOLE_INSTANCE;

	private AppointmentDAOImpl() {
		super();
	}

	public static AppointmentDAO getInstance() {
		if (SOLE_INSTANCE == null) {
			SOLE_INSTANCE = new AppointmentDAOImpl();
		}
		return SOLE_INSTANCE;
	}

	public void persist(String crm, String cpf, DateTime time, double price) {
		String timeString = parseDate(time);
		String sql = "INSERT INTO appointment(doctor, patient, time, price) VALUE (?, ?, ?, ?)";
		Object[] params = new Object[]{crm, cpf, timeString, price};
		jdbcTemplate.update(sql, params);
	}

	public List<Appointment> loadAppointments(String doctorCRM) {
		return jdbcTemplate.query("SELECT * FROM appointment WHERE doctor = ?", new Object[]{doctorCRM}, new AppointmentMapper());
	}

	public List<Appointment> loadAllAppointments() {
		return jdbcTemplate.query("SELECT * FROM appointment", new AppointmentMapper());
	}

	public void delete(String crm, String cpf, String time) {
		String sql = "DELETE FROM appointment WHERE doctor = ? AND patient = ? AND time = ?";
		Object[] params = new Object[]{crm, cpf, time};
		jdbcTemplate.update(sql, params);
	}

	public Appointment retrieve(String crm, String cpf, DateTime time) {
		String timeString = parseDate(time);
		
		try {
  			String sql = "SELECT * FROM appointment WHERE doctor = ? AND patient = ? AND time = ?";
			Object[] params = new Object[]{crm, cpf, timeString};
			return jdbcTemplate.queryForObject(sql, params, new AppointmentMapper());
		} catch(EmptyResultDataAccessException e) {
			return null;
		}
	}

	private static final class AppointmentMapper implements RowMapper<Appointment> {

		public Appointment mapRow(ResultSet rs, int rowNum) throws SQLException {
			Appointment appointment = new Appointment();
			appointment.setDoctor(DoctorDAOImpl.getInstance().retrieve(rs.getString("doctor")));
			appointment.setPatient(PatientDAOImpl.getInstance().retrieve(rs.getString("patient")));
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
			try {
				Date date = sdf.parse(rs.getString("time"));
				appointment.setTime(new DateTime(date.getTime()));
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			appointment.setPrice(rs.getDouble("price"));
			return appointment;
		}
	}
	
	private static String parseDate(DateTime time) {
		DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendYear(4, 4).appendLiteral("-").appendMonthOfYear(2).appendLiteral("-")
                .appendDayOfMonth(2).appendLiteral(" ").appendHourOfDay(2).appendLiteral(":").appendMinuteOfHour(2).toFormatter();
		
		return time.toString(dtf);
	}
}
